import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

public class UserDataThread implements Runnable {
	
	//Ссылки на менеджеры
	GraphManager graphManager;
	ProxyManager proxyManager;
	//номер потока
	int threadNumber;

	public UserDataThread(GraphManager graphman, ProxyManager proxyman, int threadnum) {
		graphManager = graphman;
		proxyManager = proxyman;
		threadNumber = threadnum;
	}

	@Override
	public void run() {
		System.out.println("UserData " + threadNumber + " started");
		//прокси
		Proxy currentProxy = proxyManager.getNextProxy();
		//id юзера, у которого читаем друзей
		Long currentUserId = graphManager.getNextUserIdForProcessing();
		
		//поток работает, пока есть прокси и есть friendы для обработки
		while (currentUserId != null && currentProxy != null) {
			//флаг полученности данных юзера
			boolean userdataReceived = false;
			
			while (!userdataReceived && currentProxy != null) {
				//флаг того, что прокси отвалился
				boolean proxyIsDead = false;
				//флаг того, что прокси исчерпал лимит запросов
				boolean proxyIsRateLimited = false;
				
				//прокси
				HttpHost proxy = new HttpHost(currentProxy.getAddress(), currentProxy.getPort(), "http");
		        DefaultHttpClient httpclient = new DefaultHttpClient();
		        
		        //вернувшийся текст
				String responseText = null;
				
				try {
					//прокси
					HttpParams params = httpclient.getParams();
					params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
					//15 сек
					HttpConnectionParams.setConnectionTimeout(params, 15000);
					HttpConnectionParams.setSoTimeout(params, 20000);
					
					HttpGet getRequest = new HttpGet("https://api.twitter.com/1/users/show.json?user_id=" + currentUserId.longValue());
					
					//делаем запрос
				    HttpResponse httpResponse = httpclient.execute(getRequest);
				    HttpEntity entity = httpResponse.getEntity();
				    //сохраняем текст респонса
				    responseText = new String(EntityUtils.toString(entity));

				    EntityUtils.consume(entity);
				} catch (Exception e) {
					//выставляем флаг отваленности
					proxyIsDead = true;
				}
				finally {
		            httpclient.getConnectionManager().shutdown();
				}
				
				//если прокся не мертвая и есть ответ
				if (!proxyIsDead && responseText != null) {
					//пробуем посмотреть, ошибка или нет
					Responses.ErrorResponse errorResponse = Responses.parseErrorResponse(responseText);
					if (errorResponse != null && errorResponse.error != null) {
						String error = errorResponse.error;
						//проверим ошибку
						if (error.contains("Rate limit exceeded")) {
							//прокси сдохла
							proxyIsRateLimited = true;
						} else if (error.contains("User has been suspended")) {
							graphManager.endUserDataProccessing(currentUserId, new Responses.UserDataResponse());
							//меняем флаг
							userdataReceived = true;
							//выведем инфу
							System.out.println("UserDataThread.run() + thread:" + threadNumber + " user has been suspended");
						} else {
							System.err.println("UserDataThread.run() thread:" + threadNumber + " unknown error, response: " + responseText);
							break;
						}
					} else {
						//Пробуем распарсить 
						Responses.UserDataResponse userData = Responses.parseUserDataResponse(responseText);
						
						if (userData != null) {
							//добавим юзердату в бд
							graphManager.endUserDataProccessing(currentUserId, userData);
							//меняем флаг
							userdataReceived = true;
							//сообщим
							System.out.println("UserDataThread.run() thread:" + threadNumber + " userdata received for " + currentUserId.longValue());
						} else {
							//не получилось - дохлая прокся
							proxyIsDead = true;
						}
					}
				}
				
				//проверим, нужно ли взять новую проксю
				if (proxyIsDead || proxyIsRateLimited) {
					currentProxy = proxyManager.getNextProxy();
					//для избежания exc
					if (currentProxy != null)
						System.out.println("UserDataThread.run() thread " + threadNumber + " proxy " + currentProxy.getAddress() + ":" + currentProxy.getPort()  + " is " + (proxyIsDead ? "dead" : "rateLimited") + ", try new");
				}
			}
			
			//продолжаем только если данные получены
			if (userdataReceived) {
				currentUserId = graphManager.getNextUserIdForProcessing();
			} else {
				break;
			}
		}	
		
		//проверим, как вышли из цикла
		if (currentUserId == null && currentProxy != null) {
			System.out.println("UserDataThread " + threadNumber + " stopped, no more users to process");
			
			//вернем прокси назад потому что она, возможно, ещё жива
			proxyManager.returnProxyToList(currentProxy);
		} else {
			System.err.println("ERROR:UserDataThread " + threadNumber + " stopped, no more proxies");
		}
	}
}
